package com.panopset.gui.container;

import static com.panopset.Util.dspmsg;
import static com.panopset.Util.isPopulated;

import java.awt.GridLayout;
import java.awt.LayoutManager;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Vector;

import javax.swing.JTextField;

import com.panopset.Alert;

/**
 * Panopset abstract text field.
 *
 * @author Karl Dinwiddie
 *
 */
public abstract class AbstractPanTextField extends PanField<JTextField>
        implements KeyListener, FocusListener {

    /**
     * Column count.
     */
    private final int cols;

    /**
     * Validators.
     */
    private final Vector<Validator> validators = new Vector<Validator>();

    /**
     * @param columns
     *            Number of columns.
     * @param borderTitle
     *            Border title.
     * @param toolTipText
     *            Tool tip text.
     */
    public AbstractPanTextField(final int columns, final String borderTitle,
            final String toolTipText) {
        this(columns, borderTitle, toolTipText, "");
    }

    /**
     *
     * @param columns
     *            Number of columns.
     * @param borderTitle
     *            Border title.
     * @param toolTipText
     *            Tool tip text.
     * @param defaultValue
     *            Default value.
     */
    public AbstractPanTextField(final int columns, final String borderTitle,
            final String toolTipText, final String defaultValue) {
        super(borderTitle, toolTipText, defaultValue);
        this.cols = columns;
        getInnerComponent().addFocusListener(this);
        getInnerComponent().addKeyListener(this);
    }

    /**
     * @return Number of columns.
     */
    public final int getColumns() {
        return cols;
    }

    /**
     * This won't do anything unless a validator has been added.
     *
     * @param value
     *            Value to validate.
     * @return Message.
     */
    protected final String validate(final String value) {
        String lastMessage = null;
        for (Validator validator : validators) {
            String msg = validator.validate(value);
            if (isPopulated(msg)) {
                lastMessage = msg;
            }
        }
        return lastMessage;
    }

    /**
     * Add a Validator to this field.
     *
     * @param validator
     *            Validator.
     */
    public final void addValidator(final Validator validator) {
        validators.add(validator);
    }

    @Override
    public final boolean isValid(final String value) {
        String msg = validate(value);
        if (isPopulated(msg)) {
            dspHighlightedMsg(msg);
        } else {
            return true;
        }
        return false;
    }

    /**
     * Override to respond to a valid value entered by the user.
     *
     * @param value
     *            New value.
     */
    protected void update(final String value) {

    }

    /**
     * Report change.
     */
    final void reportChange() {
        resetHighlighting();
        String msg = validate(getInnerComponent().getText());
        if (isPopulated(msg)) {
            dspHighlightedMsg(msg);
        } else {
            resetHighlighting();
        }
    }

    /**
     * Display highlighted message.
     *
     * @param msg
     *            Message to display.
     */
    protected final void dspHighlightedMsg(final String msg) {
        setAlertHighlighting();
        dspmsg(msg);
    }

    /**
     * Reset highlighting to default.
     */
    protected final void resetHighlighting() {
        Alert.green("");
        setNormalHighlighting();
    }

    @Override
    public final String getComponentValue() {
        return getInnerComponent().getText();
    }

    @Override
    public final void setComponentValue(final String value) {
        getInnerComponent().setText(value);
    }

    @Override
    protected abstract JTextField createComponent();

    @Override
    public void keyTyped(final KeyEvent e) {
        // nothing to do here.
    }

    @Override
    public final void keyPressed(final KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_ENTER) {
            reportChange();
        }
    }

    @Override
    public void keyReleased(final KeyEvent e) {
        // nothing to do here.
    }

    @Override
    public void focusGained(final FocusEvent e) {
        // nothing to do here.
    }

    @Override
    public final void focusLost(final FocusEvent e) {
        reportChange();
    }

    @Override
    protected final LayoutManager createLayout() {
        return new GridLayout(1, 1);
    }
}
